HAL IWDG typical use cases for migration

This section provides information about the HAL IWDG typical use case for migration.

HAL IWDG early wake-up interrupt

The table below outlines the typical scenarios for HAL1 and HAL2 regarding the IWDG peripheral:

In this scenario the user can optionally provide his own LSI frequency , start the iwdg driver and receive a callbacks (early wakeup Callbacks) that indicates a reset is going to occur, so the user can take the necessary actions before the reset.

HAL Version

Description

HAL1

In HAL1, the initialization of the IWDG peripheral was handled by a single init function. This function was responsible for both initializing and configuring its parameters, such as the Prescaler, Window, and Counter.

Steps:

  1. Uses HAL_IWDG_Init() to start the IWDG peripheral.

  2. Uses HAL_IWDG_RegisterCallback() to register the early wakeup interrupt

  3. Uses HAL_IWDG_Refresh() to refresh the IWDG peripheral.

  4. if IWDG interrupt raises, driver calls User_Callback_function .

HAL2

In HAL2, the initialization process for the IWDG driver was refined by splitting the original init API into two distinct functions: init and start.

Steps:

  1. Uses HAL_IWDG_Init() to initialize the IWDG peripheral.

  2. Optionally : uses HAL_IWDG_SetLSIFrequency() to provide user’s own LSI frequency.

  3. Uses HAL_IWDG_RegisterEarlyWakeupCallback() to register the early wakeup interrupt

  4. Uses HAL_IWDG_Start() to start the IWDG peripheral.

  5. Uses HAL_IWDG_Refresh() to manage the refresh of the IWDG counter.

  6. if IWDG interrupt raises, driver calls User_Callback_function .

Summary

  • The init function instantiates a handle and associates it with the IWDG instance.

  • The start function allows to start the IWDG according to the users parameters:
    • the prescaler is based on of maximum time given by the user in milliseconds ( it can calso be customized to use microseconds or seconds) .

    • the reload is based on of maximum time given by the user in milliseconds ( it can calso be customized to use microseconds or seconds) .

    • the window is based on of minimum time given by the user in milliseconds ( it can calso be customized to use microseconds or seconds) .

 @startuml

 rnote over "User"
  As a first step, the user manually calculates the values
  of reload, window, and prescaler and set them in the handle .
  This values can also calculated by STM32CubeMX.
 endrnote

 "User"->"Driver IWDG" : HAL_IWDG_Init()

 "Driver IWDG" --> "User": hal status : HAL_OK
 "User" ->  "Driver IWDG" : HAL_IWDG_RegisterCallback()
 "Driver IWDG" --> "User" : return HAL_OK

 alt IWDG not expired
 group Loop [Can be repeated]

 "User" -> "Driver IWDG" : HAL_IWDG_Refresh()

 rnote over "Driver IWDG"
 <color #green>Refresh done before IWDCNT
 <color #green>raches 0x000
 endrnote

 rnote over "Driver IWDG"
 <color #green> Operation ended successfully
 endrnote

 end

 else IWDG expired
 rnote over "Driver IWDG"
 <color #red> when the IWDCNT reaches EWIT -1
 endrnote
"NVIC" -> "IWDG_IRQHandler" : IWDG Early Wakeup interrupt
"IWDG_IRQHandler" -> "Driver IWDG" : HAL_IWDG_IRQHandler()

 "Driver IWDG" -> "User" :HAL_IWDG_EarlyWakeupCallback()
 end

 @enduml

Code snippet

HAL1

HAL2

/* Reload and Window register values are already calculated
by the user for the respective time values of 762ms and 400ms */
#define IWDG_WINDOW 800;  /* 40 ms */
#define IWDG_RELOAD 1561; /* 78 ms */




/* IWDG handle */
IWDG_HandleTypeDef hiwdg;

/* instance selection */
hiwdg.Instance = IWDG;

/* Set Init */
hiwdg.Init.Prescaler = IWDG_PRESCALER_16;
hiwdg.Init.Window = IWDG_WINDOW;
hiwdg.Init.Reload = IWDG_RELOAD;
hiwdg.Init.EWI = 0;


/* Init the IWDG */
HAL_IWDG_Init(&hiwdg)

/* Registering the user callback function */
 HAL_IWDG_RegisterCallback(&hiwdg, HAL_IWDG_EWI_CB_ID, User_Callback_function);









/* IWDG refresh : need to be called periodically */
  HAL_IWDG_Refresh(&hiwdg);

/* IRQHandler function */
  HAL_IWDG_IRQHandler(&hiwdg);

/* IWDG  callback function */
 HAL_IWDG_EarlyWakeupCallback(&hiwdg, HAL_IWDG_EWI_CB_ID, User_Callback_function);
/* max_time_us */
uint32_t max_time_ms = 78;
/* min_time_us */
uint32_t min_time_ms = 40;
/* early_wakeup_us must be between min_time_ms and max_time_ms  */
uint32_t early_wakeup_time_ms = 50


/* IWDG handle */
hal_iwdg_handle_t hiwdg;











/* Init the IWDG */
HAL_IWDG_Init(&hiwdg, HAL_IWDG1);

/* Registering the user callback function */
HAL_IWDG_RegisterEarlyWakeupCallback(&hiwdg, User_Callback_function);

/* User chooses to provide his own LSI frequency */
HAL_IWDG_SetLSIFrequency(&hiwdg,250);

/* Start the IWDG : prescaler / reload / window and early wakeup
are calculated from the max, min and early wakeup time */
HAL_IWDG_Start(&hiwdg, min_time_ms, max_time_ms, early_wakeup_ms);


/* IWDG refresh : need to be called periodically */
HAL_IWDG_Refresh(&hiwdg);

/* IRQHandler function */
HAL_IWDG_IRQHandler(&hiwdg);

/* IWDG  callback function */
HAL_IWDG_EarlyWakeupCallback(&hiwdg);

HAL IWDG max time adjustment

The table below outlines the typical scenarios for HAL1 and HAL2 regarding the IWDG peripheral:

In this scenario user can adjust and modify the maximum time value, according to the current maximum time and the possible value of step.

  • Maximum time corresponds to “Reset time” given by the user in milliseconds ( it can calso be customized to use microseconds or seconds) .

HAL1 Sequence Diagram

HAL2 Sequence Diagram

@startuml

    rnote over "User"
    As a first step, the user manually calculates the values
    of reload, window, and prescaler and set them in the handle .
    This values can also calculated by STM32CubeMX.
    endrnote

    "User"->"Driver IWDG" : HAL_IWDG_Init()
    group Loop [Can be repeated]
    "User" -> "Driver IWDG" : HAL_IWDG_Refresh()
    end

    rnote over "User"
    To change the Reload value,
    the user must recalculate it manually
    and set it in the handle .
    endrnote

    "User"->"Driver IWDG" : HAL_IWDG_Init()
    group Loop [Can be repeated]
    "User" -> "Driver IWDG" : HAL_IWDG_Refresh()

    end

@enduml

 @startuml


"User"->"Driver IWDG" : HAL_IWDG_Init()
"Driver IWDG" --> "User": hal status : HAL_OK

rnote over "User"
To adjust the max time
LSI frequency is set to 32000 , and user choosses 78000 us as max time.
endrnote

"User" -> "Driver IWDG" : HAL_IWDG_Start()
"Driver IWDG" --> "User": hal status : HAL_OK

group Loop [Can be repeated]

"User" -> "Driver IWDG" : HAL_IWDG_Refresh()
end

rnote over "User"
To know the max time calculated by the IWDG driver(the exact value of the application)
user can call HAL_IWDG_GetMaxTime() function.
endrnote

"User"->"Driver IWDG" : HAL_IWDG_GetMaxTime()
"Driver IWDG" -> "User" : 75000 us

rnote over "User"
To know the iwdg step
user can call HAL_IWDG_GetStep_us() function.
endrnote
"User"->"Driver IWDG" : HAL_IWDG_GetStep_us()
"Driver IWDG" -> "User" : 1638 us

rnote over "User"
User can adjust the max time according
the current time + step.
endrnote


"User" -> "Driver IWDG" : HAL_IWDG_Start()
"Driver IWDG" --> "User"

group Loop [Can be repeated]


"User" -> "Driver IWDG" : HAL_IWDG_Refresh()
end

@enduml

Code snippet

HAL1

HAL2

/* Reload and Window register values are already calculated
by the user  */
#define IWDG_WINDOW 800;  /* 400ms */
#define IWDG_RELOAD 1561; /* 78 ms */




/* IWDG handle */
IWDG_HandleTypeDef hiwdg;

/* instance selection */
hiwdg.Instance = IWDG;

/* Set Init */
hiwdg.Init.Prescaler = IWDG_PRESCALER_16;
hiwdg.Init.Window = IWDG_WINDOW;
hiwdg.Init.Reload = IWDG_RELOAD;
hiwdg.Init.EWI = 0;


/* Init the IWDG */
HAL_IWDG_Init(&hiwdg)





/* IWDG refresh : need to be called periodically */
  HAL_IWDG_Refresh(&hiwdg);


/* User recalculate the value of Reload manually and set it again */
hiwdg.Init.Reload = 0x6F ;




/* Init the IWDG */
HAL_IWDG_Init(&hiwdg)

/* IWDG refresh : need to be called periodically */
  HAL_IWDG_Refresh(&hiwdg);
/* max_time_us */
uint32_t max_time_us = 78000;
/* min_time_us */
uint32_t min_time_us = 4000;
/* early_wakeup_us must be between min_time_us and max_time_us  */
uint32_t early_wakeup_time_us = 5000;
/* returned_max_time_ms  */
uint32_t returned_max_time_us = 0;
/* returned_step_us  */
uint32_t returned_step_us = 0;
/* IWDG handle */
hal_iwdg_handle_t hiwdg;









/* Init the IWDG */
HAL_IWDG_Init(&hiwdg, HAL_IWDG1);

/* Start the IWDG : prescaler / reload / window and early wakeup are calculated
 from the max, min and early wakeup time */
HAL_IWDG_Start(&hiwdg, min_time_us, max_time_us, early_wakeup_us);

/* IWDG refresh : need to be called periodically */
HAL_IWDG_Refresh(&hiwdg);


/* Get max time configured by the IWDG */
returned_max_time_us = HAL_IWDG_GetMaxTime(&hiwdg);

/* Get the IWDG step */
returned_step_us = HAL_IWDG_GetStep_us(&hiwdg);

/* Start the IWDG  */
HAL_IWDG_Start(&hiwdg, min_time_us, ( returned_max_time_us + returned_step_us ), early_wakeup_us);

/* IWDG refresh : need to be called periodically */
HAL_IWDG_Refresh(&hiwdg);